package net.cassandraview;

import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;

import org.apache.cassandra.thrift.Cassandra;
import org.apache.cassandra.thrift.CfDef;
import org.apache.cassandra.thrift.ColumnDef;
import org.apache.cassandra.thrift.InvalidRequestException;
import org.apache.cassandra.thrift.KsDef;
import org.apache.cassandra.thrift.NotFoundException;
import org.apache.thrift.TException;
import org.richfaces.event.ItemChangeEvent;

@ManagedBean(name = "detailsPage")
@ViewScoped
public class DetailsPage implements Serializable {

	private final transient Logger log = Logger.getLogger(DetailsPage.class.getName());
	
	private static final long serialVersionUID = 1L;

	@ManagedProperty("#{userSession}")
	private UserSession session;
	
	private List<DetailProperty> serverDetails;
	
	private List<DetailProperty> keyspaceDetails;
	
	private String activeTab = "basic";

	@PostConstruct
	protected void init() {
		if (getSession().connectionActive()) {
			Cassandra.Client client = session.getClient();
			try {
				KsDef ksDef = client.describe_keyspace(getKeyspace());
				keyspaceDetails = new ArrayList<DetailProperty>();
				for (KsDef._Fields f : KsDef._Fields.values()) {
					if (!f.equals(KsDef._Fields.CF_DEFS)) {
						keyspaceDetails.add(new DetailProperty(f.name(), ksDef.getFieldValue(f)));
					}
				}
			} catch (Exception e) {
				log.log(Level.SEVERE, "Error retrieving keyspace info from cassandra.", e);
			}
		}
	}

	public List<DetailProperty> getCFPropertyList() {
		List<DetailProperty> result = null;
		CfDef cf = getColumnFamilyDefinition(getColumnFamily());
		if (cf != null) {
			result = new ArrayList<DetailProperty>();
			for (CfDef._Fields f : CfDef._Fields.values()) {
				result.add(new DetailProperty(f.name(), cf.getFieldValue(f)));
			}
		}
		return result;
	}
	
	public List<DetailProperty> getColumnsPropertyList() throws UnsupportedEncodingException {
		List<DetailProperty> result = null;
		CfDef def = getColumnFamilyDefinition(getColumnFamily());
		if (def != null) {
			result = new ArrayList<DetailProperty>();
			List<ColumnDef> columns = def.getColumn_metadata();
			for (ColumnDef cdef : columns) {
				StringBuilder builder = new StringBuilder();
				for (ColumnDef._Fields f : ColumnDef._Fields.values()) {
					builder.append(f.name()).append(" - ").append(cdef.getFieldValue(f)).append("\n");
				}
				result.add(new DetailProperty(new String(cdef.getName(), "UTF-8"), builder.toString()));
			}
		}
		return result;
	}
	
	protected CfDef getColumnFamilyDefinition(String name) {
		if (getSession().connectionActive()) {
			Cassandra.Client client = session.getClient();
			try {
				List<CfDef> cfs = client.describe_keyspace(getKeyspace()).getCf_defs();
				for (CfDef cfd : cfs) {
					if (cfd.getName().equals(name))
						return cfd;
				}
			} catch (Exception e) {
				logFailure("Error retrieving ColumnFamily definitions.", e);
			}
		} else {
			logFailure("Cannot get column family definition", null);
		}
		return null;
	}
	
	protected void logFailure(String message, Throwable e) {
		log.log(Level.SEVERE, message, e);
		FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(message));
	}
	
	public static class DetailProperty implements Serializable{
		private static final long serialVersionUID = 1L;
		private String name;
		private Object value;
		public DetailProperty(String name, Object value) {
			super();
			this.name = name;
			this.value = value;
		}
		public String getName() {
			return name;
		}
		public void setName(String name) {
			this.name = name;
		}
		public Object getValue() {
			return value;
		}
		public void setValue(Object value) {
			this.value = value;
		}
	}
	
	public UserSession getSession() {
		return session;
	}

	public void setSession(UserSession session) {
		this.session = session;
	}

	public String getKeyspace() {
		return session.getCurrentKeyspace();
	}
	
	public String getColumnFamily() {
		return session.getCurrentColumnFamily();
	}

	public List<DetailProperty> getServerDetails() {
		return serverDetails;
	}

	public void setServerDetails(List<DetailProperty> serverDetails) {
		this.serverDetails = serverDetails;
	}

	public List<DetailProperty> getKeyspaceDetails() {
		return keyspaceDetails;
	}

	public void setKeyspaceDetails(List<DetailProperty> keyspaceDetails) {
		this.keyspaceDetails = keyspaceDetails;
	}

	public String getActiveTab() {
		return activeTab;
	}

	public void setActiveTab(String activeTab) {
		this.activeTab = activeTab;
	}
	
	public void tabChangeListener(ItemChangeEvent i) {
		activeTab = i.getNewItemName();
	}
	
	
}
